﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using Microsoft.Kinect;
using Microsoft.Samples.Kinect.KinectExplorer;
using Microsoft.Samples.Kinect.WpfViewers;
using Microsoft.VisualBasic;
using Microsoft.Win32;

namespace ZeroTouchUI
{
    /// <summary>
    /// Interaction logic for NewMainWindow.xaml
    /// </summary>
    public partial class NewMainWindow : Window, INotifyPropertyChanged
    {
        private readonly Uri iconUri = new Uri("pack://application:,,,/nsa.ico", UriKind.RelativeOrAbsolute);
        private readonly Uri expIconUri = new Uri("pack://application:,,,/KinectExplorer.ico", UriKind.RelativeOrAbsolute);
        private GridLength showing = new GridLength(42), hidden = new GridLength(0);
        public GestureRecognizer recognizer;
        public NotifyIcon trayIcon;
        public NotifyIcon recognizerIcon;
        bool trayCreated = false;
        NewGestureRecorder recorder;

        System.Windows.Forms.ContextMenu trayMenu;

        public Microsoft.Samples.Kinect.KinectExplorer.KinectExplorer explorer;
        private Profile profile;
        private GestureCanvas canvas;
        private List<string> addedPrograms;
        public event PropertyChangedEventHandler PropertyChanged;
        
        private delegate void SavingDelegate();

        public NewMainWindow()
        {
            InitializeComponent();
            canvas = new GestureCanvas();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            ActivateExplorer();
            Tracking = "Not found";
            if (explorer != null &&
                explorer.sensorItems != null &&
                explorer.sensorItems.Count > 0 &&
                explorer.sensorItems[0].Sensor != null)
            {
                this.Dispatcher.BeginInvoke(new ThreadStart(() => this.kinectStatus.Content = "Kinect status: " + explorer.sensorItems[0].Sensor.Status.ToString()));
                if (explorer.sensorItems[0].Sensor.Status.ToString() == "Connected")
                {
                    recognizer = new GestureRecognizer
                    {
                        //main = this,
                        Kinect = explorer.sensorItems[0].Sensor,
                        Visibility = System.Windows.Visibility.Hidden,
                        WindowState = System.Windows.WindowState.Minimized
                    };
                    recognizer.Closing += new System.ComponentModel.CancelEventHandler(recognizer_Closing);
                    recognizer.Recognized += new GestureRecognizer.RecognizedEventHandler(recognizer_Recognized);
                    recognizer.Show();
                    recognizerIcon = new NotifyIcon();
                    recognizerIcon.Text = "NSA Recognizer - Not Tracking";
                    recognizerIcon.Icon = new Icon("KinectExplorer.ico");
                    recognizerIcon.Click += new EventHandler(recognizerIcon_Click);
                    recognizerIcon.Visible = true;
                }
            }
            else
            {
                this.Dispatcher.BeginInvoke(new ThreadStart(() => this.kinectStatus.Content = "Kinect status: Not found"));
            }

            KinectSensor.KinectSensors.StatusChanged += this.KinectsStatusChanged;
            ProfileNameText = profile.Name;
            this.PropertyChanged += new PropertyChangedEventHandler(NewMainWindow_PropertyChanged);
            DataContext = this;
            this.Update();
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            System.Windows.Application.Current.Shutdown();
        }

        private void OnExit(object sender, EventArgs e)
        {
            System.Windows.Application.Current.Shutdown();
        }

        private void ActivateExplorer()
        {
            if (explorer == null)
            {
                explorer = new Microsoft.Samples.Kinect.KinectExplorer.KinectExplorer
                {
                    Icon = BitmapFrame.Create(expIconUri),
                    Visibility = System.Windows.Visibility.Hidden,
                    WindowState = System.Windows.WindowState.Minimized
                };
                explorer.Closed += new EventHandler(Explorer_Closed);
                explorer.Show();
            }
        }

        private void InitializeLists()
        {
            List<string> gestures = new List<string>(), actions = new List<string>();
            foreach (KeyValuePair<Gesture, Action> pair in profile.getDictionary())
            {
                gestures.Add(pair.Key.Name);
            }

            foreach (Action action in profile.getActionList())
            {
                actions.Add(action.Name);
            }

            gestureView.BeginInit();
            gestureView.ItemsSource = gestures.AsEnumerable<string>();
            gestureView.EndInit();

            actionView.BeginInit();
            actionView.ItemsSource = actions.AsEnumerable<string>();
            actionView.EndInit();
        }

        private Action GetLastSelected()
        {
            string selected = (string)actionView.SelectedItems[actionView.SelectedItems.Count - 1];

            foreach (Action action in profile.getActionList())
            {
                if (action.Name == selected)
                {
                    return action;
                }
            }

            return null;
        }

        private void Restore(object sender, EventArgs e)
        {
            trayIcon.Visible = false;
            ActivateExplorer();
            this.Show();
        }
        
        private void Save()
        {
            ProfileNameText += " Saving. Please wait...";
            this.IsEnabled = false;
            Dispatcher.BeginInvoke(new System.Action(() =>
            {
                profile.SaveProfile(profile.Name);
                this.IsEnabled = true;
                ProfileNameText = profile.Name;
                if (recognizer != null)
                {
                    recognizer.profile = profile;
                }
                Dollar.templates = profile.getDictionary();
            }),
                DispatcherPriority.Background);
        }

        private void SaveAction()
        {
            if (ActionList.SelectedIndex >= 0)
            {
                string selected = (string)((ComboBoxItem)ActionList.SelectedItem).Content;
                Action action = GetLastSelected();

                if (action == null)
                {
                    return;
                }

                if (selected == "Open")
                {
                    action.Type = "1";
                    action.CustomData = "1";
                    keyRow.Height = hidden;
                    urlRow.Height = hidden;
                }
                else if (selected == "Close")
                {
                    action.Type = "1";
                    action.CustomData = "2";
                    keyRow.Height = hidden;
                    urlRow.Height = hidden;
                }
                else if (selected == "Send Keys")
                {
                    keyRow.Height = showing;
                    urlRow.Height = hidden;
                    if (String.IsNullOrEmpty(keyTextBox.Text))
                    {
                        return;
                    }

                    action.Type = "2";
                    action.CustomData = keyTextBox.Text;
                }

                action.Info = (string)((ComboBoxItem)ProgramList.SelectedItem).Content;
                for (int i = 0; i < profile.getActionList().Count; i++)
                {
                    if (action.Name == profile.getActionList()[i].Name)
                    {
                        profile.getActionList()[i] = action;
                    }
                }

                profile.pc.delete_event(action.Name);
                if (action.Type == "1")
                {
                    profile.pc.add_event1(action.Name, action.Info, action.CustomData);
                }
                else if (action.Type == "2")
                {
                    profile.pc.add_event2(action.Name, action.Info, action.CustomData);
                }

                Save();
            }
        }

        private void recorder_Saved(object sender, EventArgs e)
        {
            Gesture newGesture = new Gesture();
            if (recorder != null && recorder.gesture != null)
            {
                newGesture.Name = recorder.gesture.Name;
                if (recorder.gesture.leftGesture != null && recorder.gesture.leftGesture.Count > 0)
                {
                    newGesture.leftGesture = recorder.gesture.leftGesture;
                }
                else
                {
                    newGesture.leftGesture = new List<System.Windows.Point>();
                }

                if (recorder.gesture.rightGesture != null && recorder.gesture.rightGesture.Count > 0)
                {
                    newGesture.rightGesture = recorder.gesture.rightGesture;
                }
                else
                {
                    newGesture.rightGesture = new List<System.Windows.Point>();
                }
            }

            if (newGesture.leftGesture.Count > 0 || newGesture.rightGesture.Count > 0)
            {
                if (profile.getDictionary().Any(g => g.Key.Name.ToLower() == newGesture.Name.ToLower() && recorder.oldGesture != null && recorder.oldGesture.Name.ToLower() != g.Key.Name.ToLower()))
                {
                    NameTaken nt = new NameTaken();
                    nt.ShowDialog();
                }
                else
                {
                    if (recorder.oldGesture != null)
                    {
                        List<Gesture> gestures = new List<Gesture>();
                        foreach (Gesture gesture in profile.getDictionary().Keys)
                        {
                            gestures.Add(gesture);
                        }
                        foreach (Gesture gesture in gestures)
                        {
                            if (gesture.Name.ToLower() == recorder.oldGesture.Name.ToLower())
                            {
                                profile.AddGesture(newGesture, profile.getDictionary()[gesture]);
                                profile.RemoveGesture(gesture);
                                break;
                            }
                        }
                    }
                    else
                    {
                        profile.AddGesture(newGesture, new Action("No Action", "", ""));
                    }

                    InitializeLists();
                    gestureView.SelectedItems.Clear();
                    gestureView.SelectedItem = newGesture.Name;
                    Save();
                }
            }

            recorder.Close();
        }

        private void recorder_Closed(object sender, EventArgs e)
        {
            this.Activate();
        }

        private void Update()
        {
            if (profile != null)
            {
                if (recognizer != null)
                {
                    recognizer.profile = profile;
                }
                Dollar.templates = profile.getDictionary();

                gestureView.SelectionChanged -= gestureView_SelectionChanged;
                actionView.SelectionChanged -= actionView_SelectionChanged;
                CommandList.SelectionChanged -= CommandList_SelectionChanged;
                ProgramList.SelectionChanged -= ProgramList_SelectionChanged;

                InitializeLists();

                if (gestureView.SelectedItem != null)
                {
                    Gesture active = new Gesture();
                    foreach (Gesture g in profile.getDictionary().Keys)
                        if (g.Name == gestureView.SelectedItem.ToString())
                            active = g;
                }

                CommandList.Items.Clear();
                CommandList.Items.Add(new ComboBoxItem { Content = "No Action" });
                CommandList.Items.Add(new ComboBoxItem { Content = "Toggle Windows Mute" });
                CommandList.Items.Add(new ComboBoxItem { Content = "Raise Volume" });
                CommandList.Items.Add(new ComboBoxItem { Content = "Lower Volume" });
                CommandList.Items.Add(new ComboBoxItem { Content = "Max Volume" });
                CommandList.Items.Add(new ComboBoxItem { Content = "iTunes Next Track" });
                CommandList.Items.Add(new ComboBoxItem { Content = "iTunes Previous Track" });
                CommandList.Items.Add(new ComboBoxItem { Content = "iTunes Play" });
                CommandList.Items.Add(new ComboBoxItem { Content = "iTunes Pause" });
                CommandList.Items.Add(new ComboBoxItem { Content = "iTunes Stop" });
                CommandList.Items.Add(new ComboBoxItem { Content = "iTunes Toggle Mute" });

                ProgramList.Items.Clear();
                ProgramList.Items.Add(new ComboBoxItem { Content = "Web Browser" });

                List<Action> action_list = profile.getActionList();
                addedPrograms = new List<string>();
                foreach (Action aa in action_list)
                {
                    ComboBoxItem cbi = new ComboBoxItem();
                    cbi.Content = aa.Name;
                    CommandList.Items.Add(cbi);
                    if (!aa.Info.StartsWith("http://") && !addedPrograms.Any(s => s == aa.Info))
                    {
                        ComboBoxItem cbi2 = new ComboBoxItem();
                        cbi2.Content = aa.Info;
                        ProgramList.Items.Add(cbi2);
                        addedPrograms.Add(aa.Info);
                    }
                }
                ProgramList.Items.Add(new ComboBoxItem { Content = "New Program..." });

                UpdateGesture();
                UpdateAction();
            }

            gestureView.SelectionChanged += gestureView_SelectionChanged;
            actionView.SelectionChanged += actionView_SelectionChanged;
            CommandList.SelectionChanged += CommandList_SelectionChanged;
            ProgramList.SelectionChanged += ProgramList_SelectionChanged;
        }

        private void UpdateGesture()
        {
            gestureCanvas.Children.Remove(canvas);
            if (gestureView.SelectedItems != null && gestureView.SelectedItems.Count > 0)
            {
                CommandList.IsEnabled = true;
                Gesture shownGesture = new Gesture();
                foreach (Gesture gesture in profile.getDictionary().Keys)
                {
                    if (gesture.Name == (string)gestureView.SelectedItems[gestureView.SelectedItems.Count - 1])
                    {
                        shownGesture = gesture;
                        foreach (ComboBoxItem cbi in CommandList.Items)
                        {
                            if ((string)cbi.Content == profile.getDictionary()[gesture].Name)
                            {
                                CommandList.SelectedItem = cbi;
                                break;
                            }
                        }
                        break;
                    }
                }
                canvas = new GestureCanvas { gesture = shownGesture };
                gestureCanvas.Children.Add(canvas);
                removeGesture.IsEnabled = true;
            }
            else
            {
                CommandList.IsEnabled = false;
                removeGesture.IsEnabled = false;
            }
        }

        private void UpdateProgram(ComboBoxItem removedItem)
        {
            if (ProgramList.SelectedIndex < 0)
            {
                actionRow.Height = hidden;
                keyRow.Height = hidden;
                urlRow.Height = hidden;
                return;
            }
            if ((string)((ComboBoxItem)ProgramList.SelectedItem).Content == "Web Browser")
            {
                programRow.Height = showing;
                actionRow.Height = hidden;
                keyRow.Height = hidden;
                urlRow.Height = showing;

                if (!String.IsNullOrEmpty(urlTextBox.Text))
                {
                    Action action = GetLastSelected();
                    action.Type = "1";
                    action.CustomData = "1";
                    action.Info = "http://" + urlTextBox.Text;

                    for (int i = 0; i < profile.getActionList().Count; i++)
                    {
                        if (action.Name == profile.getActionList()[i].Name)
                        {
                            profile.getActionList()[i] = action;
                        }
                    }

                    profile.pc.delete_event(action.Name);
                    profile.pc.add_event1(action.Name, action.Info, action.CustomData);

                    Save();
                }

                return;
            }
            else if ((string)((ComboBoxItem)ProgramList.SelectedItem).Content == "New Program...")
            {
                Microsoft.Win32.OpenFileDialog open = new Microsoft.Win32.OpenFileDialog();
                open.DefaultExt = ".exe";

                if (open.ShowDialog() == true && System.IO.Path.GetExtension(open.FileName) == ".exe")
                {
                    string filename = System.IO.Path.GetFileNameWithoutExtension(open.FileName);
                    if (!addedPrograms.Any(s => s == filename))
                    {
                        ComboBoxItem cbi = new ComboBoxItem { Content = filename };
                        ProgramList.Items.Insert(ProgramList.Items.Count - 1, cbi); // Inserted such that "New Program..." is still last
                        addedPrograms.Add(filename);
                        ProgramList.SelectedItem = cbi;
                    }
                    else
                    {
                        foreach (ComboBoxItem cbi in ProgramList.Items)
                        {
                            if ((string)cbi.Content == filename)
                            {
                                ProgramList.SelectedItem = cbi;
                                break;
                            }
                        }
                    }
                }
                else
                {
                    if (open.FileName != String.Empty)
                    {
                        System.Windows.MessageBox.Show("Please select an executable application file.\n\n Example: \"notepad.exe\"",
                                                       "Incorrect File Type", MessageBoxButton.OK, MessageBoxImage.Information);
                    }
                    ProgramList.SelectionChanged -= ProgramList_SelectionChanged;
                    ProgramList.SelectedItem = removedItem;
                    ProgramList.SelectionChanged += ProgramList_SelectionChanged;
                    return;
                }
            }

            ActionList.SelectedIndex = -1;
            urlRow.Height = hidden;
            actionRow.Height = showing;
            SaveAction();
        }

        private void UpdateAction()
        {
            if (actionView.SelectedItems != null && actionView.SelectedItems.Count > 0)
            {
                Action activeAction = GetLastSelected();
                if (activeAction == null)
                {
                    return;
                }

                if (activeAction.Type == "1")
                {
                    if (activeAction.Info.StartsWith("http://"))
                    {
                        // Set to open a website
                        foreach (ComboBoxItem cbi in ProgramList.Items)
                        {
                            if ((string)cbi.Content == "Web Browser")
                            {
                                ProgramList.SelectedItem = cbi;
                                ActionList.SelectedIndex = -1;
                                keyTextBox.Text = String.Empty;
                                urlTextBox.Text = (string)activeAction.Info.Substring(7); // skips "http://"

                                programRow.Height = showing;
                                actionRow.Height = hidden;
                                keyRow.Height = hidden;
                                urlRow.Height = showing;

                                break;
                            }
                        }
                    }
                    else
                    {
                        // Set to open or close a file
                        foreach (ComboBoxItem cbi in ProgramList.Items)
                        {
                            if ((string)cbi.Content == activeAction.Info)
                            {
                                foreach (ComboBoxItem cbia in ActionList.Items)
                                {
                                    if (((string)cbia.Content == "Open" && activeAction.CustomData == "1") ||
                                        ((string)cbia.Content == "Close" && activeAction.CustomData == "2"))
                                    {
                                        ProgramList.SelectedItem = cbi;
                                        ActionList.SelectedItem = cbia;
                                        keyTextBox.Text = String.Empty;
                                        urlTextBox.Text = String.Empty;

                                        programRow.Height = showing;
                                        actionRow.Height = showing;
                                        keyRow.Height = hidden;
                                        urlRow.Height = hidden;

                                        break;
                                    }
                                }

                                break;
                            }
                        }
                    }
                }
                else if (activeAction.Type == "2")
                {
                    // Set to send a keyset to a program
                    foreach (ComboBoxItem cbi in ProgramList.Items)
                    {
                        if ((string)cbi.Content == activeAction.Info)
                        {
                            foreach (ComboBoxItem cbia in ActionList.Items)
                            {
                                if ((string)cbia.Content == "Send Keys")
                                {
                                    ProgramList.SelectedItem = cbi;
                                    ActionList.SelectedItem = cbia;
                                    keyTextBox.Text = activeAction.CustomData;
                                    urlTextBox.Text = String.Empty;

                                    programRow.Height = showing;
                                    actionRow.Height = showing;
                                    keyRow.Height = showing;
                                    urlRow.Height = hidden;

                                    break;
                                }
                            }

                            break;
                        }
                    }
                }

                removeAction.IsEnabled = true;
            }
            else
            {
                programRow.Height = hidden;
                actionRow.Height = hidden;
                keyRow.Height = hidden;
                urlRow.Height = hidden;
                removeAction.IsEnabled = false;
            }
        }

        private void gestureView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            CommandList.SelectionChanged -= CommandList_SelectionChanged;
            UpdateGesture();
            CommandList.SelectionChanged += CommandList_SelectionChanged;
        }

        private void actionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ActionList.SelectionChanged -= ActionList_SelectionChanged;
            UpdateAction();
            ActionList.SelectionChanged += ActionList_SelectionChanged;
        }

        private void CommandList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (profile != null && gestureView != null && gestureView.SelectedItems.Count > 0)
            {
                string selected = (string)gestureView.SelectedItems[gestureView.SelectedItems.Count - 1];
                foreach (Gesture gesture in profile.getDictionary().Keys)
                {
                    if (gesture.Name == selected)
                    {
                        profile.getDictionary()[gesture].Name = (string)((ComboBoxItem)CommandList.SelectedItem).Content;
                        foreach (Action action in profile.getActionList())
                        {
                            if (action.Name == (string)((ComboBoxItem)CommandList.SelectedItem).Content)
                            {
                                profile.getDictionary()[gesture].CustomData = action.CustomData;
                                profile.getDictionary()[gesture].Info = action.Info;
                                profile.getDictionary()[gesture].Type = action.Type;
                                break;
                            }
                        }
                        break;
                    }
                }

                Save();
            }
        }

        private void ProgramList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            UpdateProgram(e.RemovedItems.Count > 0 ? (ComboBoxItem)e.RemovedItems[0] : null);
        }

        private void ActionList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {            
            SaveAction();
        }

        private void exitButton_Click(object sender, RoutedEventArgs e)
        {
            (new ProfileSelect { explorer = this.explorer }).Show();
            if (recognizer != null)
            {
                recognizer.Closing -= this.recognizer_Closing;
                recognizer.Close();
            }
            this.Closed -= this.Window_Closed;
            this.Close();
        }

        private void hideButton_Click(object sender, RoutedEventArgs e)
        {
            if (!trayCreated)
            {
                trayIcon = new NotifyIcon();
                trayMenu = new System.Windows.Forms.ContextMenu();
                trayMenu.MenuItems.Add("Bring up Console", Restore);
                trayMenu.MenuItems.Add("Exit", OnExit);
                trayIcon.Text = "NSA Console";
                trayIcon.Icon = new Icon("nsa.ico");
                trayIcon.ContextMenu = trayMenu;
                trayIcon.Click += new EventHandler(Restore);
            }
            trayIcon.Visible = true;
            this.Hide();
            if (this.explorer != null)
            {
                explorer.Hide();
            }
        }

        private void saveButton_Click(object sender, RoutedEventArgs e)
        {
            string newName = Interaction.InputBox("Enter new profile name: ", "Save As", profile.Name);
            if (newName != null && newName.Count() > 0)
            {
                profile.Name = newName;
                profile.SaveProfile(profile.Name);
                profileName.Content = profile.Name;
            }
        }

        private void deleteButton_Click(object sender, RoutedEventArgs e)
        {
            string messageBoxText = "Are you sure you want to delete " + profile.Name + "?";
            string caption = "Delete Profile";
            MessageBoxButton button = MessageBoxButton.YesNo;
            MessageBoxImage icon = MessageBoxImage.Warning;

            MessageBoxResult result = System.Windows.MessageBox.Show(messageBoxText, caption, button, icon);

            if (result == MessageBoxResult.No)
            {
                return;
            }

            string file = System.IO.Path.GetFullPath(profile.Name + ".xml");
            if (System.IO.File.Exists(file))
            {
                System.IO.File.Delete(file);
            }

            (new ProfileSelect { explorer = this.explorer }).Show();
            if (recognizer != null)
            {
                recognizer.Closing -= this.recognizer_Closing;
                recognizer.Close();
            }

            this.Closed -= this.Window_Closed;
            this.Close();
        }

        private void addNewGesture_Click(object sender, RoutedEventArgs e)
        {
            bool sensorDetected = !(explorer == null ||
                                    explorer.sensorItems == null ||
                                    explorer.sensorItems.Count == 0 ||
                                    explorer.sensorItems[0].Sensor == null);

            KinectSensor ks = sensorDetected ? explorer.sensorItems[0].Sensor : null;
            if (recognizer != null)
            {
                recognizer.triggering = false;
            }
            recorder = new NewGestureRecorder(this) { Kinect = ks };
            recorder.Saved += this.recorder_Saved;
            recorder.ShowDialog();
            if (recognizer != null)
            {
                recognizer.triggering = true;
            }
        }

        private void addNewAction_Click(object sender, RoutedEventArgs e)
        {
            NewAddNewAction nana = new NewAddNewAction(profile);
            nana.Saved += new SavedEventHandler(addNewAction_Saved);
            nana.ShowDialog();
        }

        private void addNewAction_Saved(object sender, EventArgs e)
        {
            if (((NewAddNewAction)sender).oldAction != null)
            {
                for (int i = 0; i < CommandList.Items.Count; i++)
                {
                    if ((string)((ComboBoxItem)CommandList.Items[i]).Content == ((NewAddNewAction)sender).oldAction.Name)
                    {
                        ((ComboBoxItem)CommandList.Items[i]).Content = ((NewAddNewAction)sender).action.Name;
                        break;
                    }
                }
            }
            else
            {
                CommandList.Items.Add(new ComboBoxItem { Content = ((NewAddNewAction)sender).action.Name });
            }

            InitializeLists();
            Save();
        }

        private void removeGesture_Click(object sender, RoutedEventArgs e)
        {
            List<Gesture> selected = new List<Gesture>();
            foreach (string removed in gestureView.SelectedItems)
            {
                foreach (Gesture gesture in profile.getDictionary().Keys)
                {
                    if (removed == gesture.Name)
                    {
                        selected.Add(gesture);
                        break;
                    }
                }
            }
            foreach (Gesture gesture in selected)
            {
                profile.RemoveGesture(gesture);
            }

            List<string> gestures = new List<string>();
            foreach (KeyValuePair<Gesture, Action> pair in profile.getDictionary())
            {
                gestures.Add(pair.Key.Name);
            }

            InitializeLists();

            gestureView.SelectedItems.Clear();
            gestureView.SelectedIndex = -1;
            CommandList.SelectedIndex = -1;
            Save();
        }

        private void removeAction_Click(object sender, RoutedEventArgs e)
        {
            List<Action> selected = new List<Action>();
            foreach (string removed in actionView.SelectedItems)
            {
                foreach (Action action in profile.getActionList())
                {
                    if (removed == action.Name)
                    {
                        selected.Add(action);
                        break;
                    }
                }
            }
            foreach (Action action in selected)
            {
                profile.RemoveAction(action);
                List<Gesture> gestures = new List<Gesture>();
                foreach (Gesture gesture in profile.getDictionary().Keys)
                {
                    gestures.Add(gesture);
                }

                foreach (Gesture gesture in gestures)
                {
                    if (profile.getDictionary()[gesture].Name == action.Name)
                    {
                        profile.getDictionary()[gesture] = new Action("No Action", "", "");
                        if (gestureView.SelectedItems.Count > 0 && gesture.Name == (string)gestureView.SelectedItems[gestureView.SelectedItems.Count - 1])
                        {
                            CommandList.SelectedIndex = 0;
                        }
                    }
                }

                for (int i = 0; i < CommandList.Items.Count; i++)
                {
                    if ((string)((ComboBoxItem)CommandList.Items[i]).Content == action.Name)
                    {
                        CommandList.Items.Remove((ComboBoxItem)CommandList.Items[i]);
                    }
                }
            }

            InitializeLists();

            actionView.SelectedItems.Clear();
            actionView.SelectedIndex = -1;
            Save();
        }

        private void gestureItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            bool sensorDetected = !(explorer == null ||
                                    explorer.sensorItems == null ||
                                    explorer.sensorItems.Count == 0 ||
                                    explorer.sensorItems[0].Sensor == null);

            KinectSensor ks = sensorDetected ? explorer.sensorItems[0].Sensor : null;
            
            Gesture selected = new Gesture();
            if (gestureView.SelectedItems != null && gestureView.SelectedItems.Count > 0)
            {
                foreach (Gesture gesture in profile.getDictionary().Keys)
                {
                    if (gesture.Name == (string)gestureView.SelectedItems[gestureView.SelectedItems.Count - 1])
                    {
                        selected = gesture;
                        break;
                    }
                }
            }

            if (recognizer != null)
            {
                recognizer.triggering = false;
            }
            recorder = new NewGestureRecorder(this, selected) { Kinect = ks };
            recorder.Saved += this.recorder_Saved;
            recorder.ShowDialog();
            if (recognizer != null)
            {
                recognizer.triggering = true;
            }
        }

        private void actionItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (actionView.SelectedItems != null && actionView.SelectedItems.Count > 0)
            {
                NewAddNewAction nana = new NewAddNewAction(profile, (string)actionView.SelectedItems[actionView.SelectedItems.Count - 1]);
                nana.Saved += new SavedEventHandler(addNewAction_Saved);
                nana.ShowDialog();
            }
        }

        private void keyTextBox_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
         {
            if (e.Key == Key.Enter)
            {
                SaveAction();
            }
        }

        private void urlTextBox_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                UpdateProgram(null);
            }
        }

        private void keyTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            SaveAction();
        }

        private void urlTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            UpdateProgram(null);
        }

        private void recognizer_Recognized(object sender, RecognizedEventArgs e)
        {
            this.Dispatcher.BeginInvoke(new ThreadStart(() => lastRecognized.Content = "Last recognized: " + e.gesture.Name));
        }

        private void recognizer_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (recognizer != null)
            {
                e.Cancel = true;
                recognizer.Visibility = System.Windows.Visibility.Hidden;
                recognizer.WindowState = System.Windows.WindowState.Minimized;
            }
        }

        private void recognizerIcon_Click(object sender, EventArgs e)
        {
            if (recognizer != null)
            {
                recognizer.Visibility = System.Windows.Visibility.Visible;
                recognizer.Show();
                recognizer.WindowState = System.Windows.WindowState.Normal;
                recognizer.Activate();
            }
        }

        private void KinectsStatusChanged(object sender, StatusChangedEventArgs e)
        {
            this.Dispatcher.BeginInvoke(new ThreadStart(() => this.kinectStatus.Content = "Kinect status: " + e.Status.ToString()));

            Tracking = "Not found";
            if (explorer != null &&
                explorer.sensorItems != null &&
                explorer.sensorItems.Count > 0 &&
                explorer.sensorItems[0].Sensor != null &&
                e.Status.ToString() == "Connected")
            {
                recognizer = new GestureRecognizer
                {
                    //main = this,
                    Kinect = explorer.sensorItems[0].Sensor,
                    Visibility = System.Windows.Visibility.Hidden,
                    WindowState = System.Windows.WindowState.Minimized,
                    profile = this.profile
                };
                recognizer.Show();
                recognizer.Closing += new System.ComponentModel.CancelEventHandler(recognizer_Closing);
                recognizer.Recognized += new GestureRecognizer.RecognizedEventHandler(recognizer_Recognized);
                if (recognizerIcon == null)
                {
                    recognizerIcon = new NotifyIcon();
                }
                recognizerIcon.Text = "NSA Recognizer - Not Tracking";
                recognizerIcon.Icon = new Icon("KinectExplorer.ico");
                recognizerIcon.Click += new EventHandler(recognizerIcon_Click);
                recognizerIcon.Visible = true;

                if (recorder != null)
                {
                    recorder.Kinect = explorer.sensorItems[0].Sensor;
                }
            }
            else
            {
                if (recognizer != null)
                {
                    recognizer.Closing -= recognizer_Closing;
                    recognizer.Close();
                }
                if (recorder != null)
                {
                    recorder.Kinect = null;
                }
            }
        }

        private void Explorer_Closed(object sender, EventArgs e)
        {
            foreach (KinectSensorItem kinect in explorer.sensorItems)
            {
                if (kinect.Window != null)
                {
                    kinect.Window.Close();
                }
            }

            explorer = null;
        }

        private void NewMainWindow_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "ProfileNameText")
            {
                this.Dispatcher.BeginInvoke(new ThreadStart(() => profileName.Content = ProfileNameText));
            }
            else if (e.PropertyName == "Tracking")
            {
                this.Dispatcher.BeginInvoke(new ThreadStart(() => skeletonStatus.Content = "Skeleton status: " + Tracking));
            }
        }

        protected void NotifyPropertyChanged(string info)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }

        private string profileNameText;
        public string ProfileNameText
        {
            get
            {
                return profileNameText;
            }
            set
            {
                profileNameText = value;
                this.NotifyPropertyChanged("ProfileNameText");
            }
        }

        private string tracking = String.Empty;
        public string Tracking
        {
            get
            {
                return tracking;
            }
            set
            {
                tracking = value;
                this.NotifyPropertyChanged("Tracking");
            }
        }

        public Profile Profile
        {
            get
            {
                return profile;
            }
            set
            {
                profile = value;
            }
        }
    }
}
